const START = "START";
const END = "END";

export class Layout {
  constructor(data) {
    this.data = data;
    this.init();
  }

  init() {
    let nodeMap = {};
    this.data.forEach((item, index) => {
      nodeMap[item.stateId] = item;
      item.x = 0;
      item.y = 0;
      item.type === START && (this.startIndex = index);
      item.type === END && (this.endIndex = index);
    });
    this.nodeMap = nodeMap;
  }

  autoLayout() {
    if (this.data.length == 0) {
      return null;
    }

    let startNode = this.data[this.startIndex];

    let position = this.computeStartNodePosition();
    this.setNodePositon(startNode, position);

    // 递归计算每个节点相对开始节点位置, 从 start 子节点开始，
    this.recursionNodePosition(startNode);
    console.log(this.data);
    // 自动定位
    this.initScroll();
  }

  computeStartNodePosition() {
    if (this.startIndex < 0) return null;
    let svgWidth = document.getElementById("svg").width.baseVal.value;
    let svgGroupWidth = document.getElementById("svg-group").getBBox().width;
    let diffWidth = (svgWidth - svgGroupWidth) / 2;

    return { x: diffWidth, y: 10 };
  }

  setNodePositon(node, { x, y }) {
    if (node.type === END) {
      node.x = this.data[this.startIndex].x;
      node.y = y > node.y ? y : node.y;
    } else {
      node.x = x;
      node.y = y;
    }
  }

  recursionNodePosition(node) {
    let { branches } = node;
    if (!branches || branches.length < 0) return;

    let allBranchWidth = this.getBranchsWidth(branches);
    let { width: parentWidth, height: parentHeight } = this.getNodeRect(node.stateId);
    let offsetWidth = 0;
    branches.forEach(({ nextStateId: stateId }, branchIndex) => {
      let currentNode = this.getNodeByStateId(stateId);
      let { width } = this.getNodeRect(stateId);

      let position = this.computeNodePosition(
        node.x,
        node.y,
        allBranchWidth,
        parentWidth,
        parentHeight,
        offsetWidth
      );
      offsetWidth += width + 20;
      this.setNodePositon(currentNode, position);
      this.recursionNodePosition(currentNode);
    });
  }
  getNodeRect(id) {
    let el = document.getElementById(id);
    return el
      ? {
          width: el.offsetWidth,
          height: el.offsetHeight
        }
      : {};
  }

  computeNodePosition(rootX, rootY, allBranchWidth, parentWidth, parentHeight, offsetWidth) {
    const YGap = 100;
    let x, y;
    x = rootX + parentWidth / 2 - allBranchWidth / 2 + offsetWidth;
    y = rootY + parentHeight + YGap;

    return {
      x,
      y
    };
  }

  getNodeByStateId(stateId) {
    return this.nodeMap[stateId];
  }

  getBranchsWidth(branchs) {
    let sum = branchs.reduce((acc, current) => {
      let { width } = this.getNodeRect(current.nextStateId);
      return acc + width + 20;
    }, 0);
    return sum;
  }

  initScroll() {
    setTimeout(() => {
      let svg = document.getElementById("svg").width.baseVal.value;
      let workSpace = document.getElementById("work-space").offsetWidth;
      document.getElementById("work-space").scrollLeft = (svg - workSpace) / 2;
      window.scrollTo(0, 0);
    });
  }
}
